#include <iostream>
#include <stdlib.h>
#include "Init.h"
#include "cards.h"
#include "player.h"
#include "message.h"
#include "SDL.h"
#include "SDL_ttf.h"

#define VERSION "1.0b"

using namespace std;

/*
	InitGame()
	Should start the game and show first two cards to
	player. This function should be started twice, first
	for computer, second for human. who is information of
	player - 0 is computer, 1 is human
	mch -> messageCashHuman
	Play returns true if human has not passed 21, otherwise
	returns false.
	bool sp is abervation for special to show hidden card.
*/
bool Play(Init &i, Player &p, Cards &c, int who, bool sp)
{
	string mc_s, ms_s;
	int val, cardVal, xC, yC, xCa, yCa, xS, yS;
	
	SDL_Surface *image = i.GetImageAddress();
	SDL_Surface *mess_cash = NULL, *mess_score;
	SDL_Surface *screen = i.GetScreenAddress();

	/*
		Define who is player
	*/
	if (who == 0) {
		xC = COMPUTER_X;
		yC = COMPUTER_Y;
		xCa = 0;
		yCa = CARD_SCORE_POS_COMP_Y;
		xS = 0;
		yS = SCORE_POS_COMP_Y;
	} else {
		xC = HUMAN_X;
		yC = HUMAN_Y;
		xCa = 0;
		yCa = CARD_SCORE_POS_HUMAN_Y;
		xS = 0;
		yS = SCORE_POS_HUMAN_Y;
	}
	i.DeletePieceOfScreen(xCa, yCa);
	/*
		Init font
	*/
	TTF_Font *font = NULL;
	SDL_Color textColor = {255, 255, 255};
	if (TTF_Init() == -1)
		exit(0);
	font = TTF_OpenFont("pic/Ubuntu.ttf", 24);
	
	val = c.CalculateCardNb();
	cardVal = c.CalculateCardValue(val, p.GetCardsScore());
	p.UpdateCardScore(cardVal);
	SDL_Rect *clip = c.GetClipAddress(val);
	int cash = p.GetCash();
	mc_s = i.ConvertIntToString(cash);
	mc_s = "Cash: " + mc_s;
	const char *mc_c = mc_s.c_str();
	mess_cash = TTF_RenderText_Solid(font, mc_c, textColor);
	ms_s = i.ConvertIntToString(p.GetCardsScore());
	ms_s = "Score: " + ms_s;
	const char *ms_c = ms_s.c_str();
	mess_score = TTF_RenderText_Solid(font, ms_c, textColor);
	i.MySDL_ApplySurface(xCa, yCa, mess_cash, screen);
	i.MySDL_ApplySurface(xS, yS, mess_score, screen);
	if (sp == true) {
		//Fixed issue 6 for graphic.
		//Now hidden card is shown at normal position
		i.MySDL_ApplySurface(COMPUTER_X, yC, image,
				     screen, clip);
		int val = p.GetRememberedCard(1);
		clip = c.GetClipAddress(val);
		i.MySDL_ApplySurface(COMPUTER_X+40, yC, image,
				     screen, clip);
		p.UpdateTurnMinus();
	}
	else
		i.MySDL_ApplySurface(p.GetCardCoordinates(xC),
				     yC, image, screen, clip);
	p.RememberCard(val);
	p.UpdateTurn();
	
	/*
	Check if whole card score is above 21
	*/
	if (p.GetCardsScore() >= 21)	//End of game
		return true;
	else
		return false;
}

/*
	Play()
	Should play every step in the game
*/
void InitGame(Init &i, Player &p, Cards &c)
{
	int xC = COMPUTER_X;
	int yC = COMPUTER_Y;
	SDL_Surface *image = i.GetImageAddress();
	SDL_Surface *screen = i.GetScreenAddress();
	SDL_Rect *clip = c.GetClipAddress(52);	//hidden card
	i.MySDL_ApplySurface(xC, yC, image, screen, clip);
	p.UpdateTurn();
}

void ShowHiddenCard(Init &i, Player &p, Cards &c)
{
	Play(i, p, c, 0, true);
}

void HandleGame(Init &i, Player &p1, Player &p2, Cards &c)
{
	SDL_Event event;
	bool quit = false;
	
	InitGame(i, p1, c);
	Play(i, p1, c, 0, false);
	Play(i, p2, c, 1, false);
	Play(i, p2, c, 1, false);
	
	//check if some of players get black jack immediately
	//after cards have been given to them
	if (p1.GetCardsScore() == 21 ||
		   p2.GetCardsScore() == 21)
		return;

	while (quit == false) {
		while (SDL_PollEvent(&event)) {
			if (event.type == SDL_KEYDOWN) {
				switch (event.key.keysym.sym) {
					case SDLK_h:
						if (Play(i, p2, c, 1,
								false) == true)
							quit = true;
						break;
					case SDLK_s:
						quit = true;
						break;
					case SDLK_q:
						exit(0);
				}
			} else if (event.type == SDL_QUIT)
				exit(0);
		}
	}
}

/*
	Reset everything except cash!
*/
void ResetAll(Init &i, Player &p1, Player &p2, Cards &c)
{
	c.ResetAll();
	p1.ResetAll();
	p2.ResetAll();
	return;
}

void ResetCash(Player &p1, Player &p2)
{
	p1.ResetCash();
	p2.ResetCash();
	return;
}

void RefreshComputer(Init &i, Player &p, Cards &c, int *mem_cards)
{
	//first we need to delete current dealer cards
	ShowHiddenCard(i, p, c);
}

int main(int argc, char *argv[])
{
	Init init;
	Cards cards;
	Player human, computer;
	Message messages;
	SDL_Surface *screen, *background;
	screen = background = NULL;
	SDL_Event event;
	unsigned int value, card_value;
	bool game = true;
		
	//Everything about font
	TTF_Font *font = NULL;
	SDL_Color textColor = {255, 255, 255};
	if (TTF_Init() == -1)
		exit(0);
	font = TTF_OpenFont("pic/Ubuntu.ttf", 24);
		
	//Load background and screen
	if (init.MySDL_Load_Image("pic/back.jpg", 2) == true) {
		screen = init.GetScreenAddress();
		background = init.GetBackgroundImageAddress();
	} else {
		perror("init");
		exit(0);
	}
		
	//Load cards
	if (init.MySDL_Load_Image("pic/cards.png", 1) == false) {
		perror("cards.png");
		exit(0);
	}

	//Apply surface if screen && background != NULL
	if (screen && background) {
		while (game == true) {
			init.MySDL_ApplySurface(0, 0, background, screen);
			
			//Play by human
			HandleGame(init, computer, human, cards);

			//Check if human has passed limit card score
			if (human.GetCardsScore() > 21) {	//HUMAN LOST
				computer.UpdateCash(100, false);
				human.UpdateCash(100, true);
				messages.EndGame(0);
			} else {	//COMPUTER TURN
				ShowHiddenCard(init, computer, cards);
				
				/*
					Handle computer game:
					if computer win give them 100
					if human win give him 100
					if nobody win don't change result
				*/
				while (true) {
					if (computer.GetCardsScore()
						< human.GetCardsScore())
						Play(init, computer,
							cards, 0, false);
					else if (computer.GetCardsScore()
						> 21) {
						computer.UpdateCash(100, true);
						human.UpdateCash(100, false);
						messages.EndGame(1);
						break;
					}
					else if (computer.GetCardsScore()
						== human.GetCardsScore())
						break;
					else {
						computer.UpdateCash(100,
								false);
						human.UpdateCash(100, true);
						messages.EndGame(0);
						break;
					}
				}
			}
			SDL_Delay(3500);
			ResetAll(init, human, computer, cards);
			
			//ADD: REPORT THAT GAME IS FINISHED BECAUSE SOMEONE HAS
			//LOST ALL MONEY. RESET FOR MONEY WORKS.
			if (human.isMinus() == true ||
						 computer.isMinus() == true) {
				messages.Lose();
				SDL_Delay(2000);
				ResetCash(human, computer);
			}
		}
	} else {
		perror("screen or background NULL");
		exit(0);
	}
	
	return 0;
}